package com.lagou.rpc.consumer.loadbalancer;

import com.lagou.rpc.consumer.client.RpcClient;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

/**
 * @Authther: mrwu
 * @date:2021/4/6-04
 * @Description:com.lagou.rpc.consumer.loadbalancer
 */
public class RpcBalancer {
    private List<RpcClient> balancer = new ArrayList<>();
    private int point=0;//当前坐标
    private List<String> children = new ArrayList<>();
    private  ZkClient zkClient = new ZkClient("127.0.0.1:2181");

    public RpcBalancer() {
        //获取节点信息并监控节点变化
        String path = "/rpcservice";
        //1获取子节点
        children = zkClient.getChildren(path);
        handlechildren(children);
        //监听节点变化
        zkClient.subscribeChildChanges(path, new IZkChildListener() {
            @Override
            public void handleChildChange(String s, List<String> list) throws Exception {
                children.forEach(node->{
                    if (!list.contains(node)){
                        System.out.println(node+"下线");
                        balancer.get(children.indexOf(node)).close();//先关闭资源
                        balancer.remove(children.indexOf(node));//移除
                        children.remove(node);//删除此节点
                    }
                });
                list.forEach(node->{
                    if (!children.contains(node)){
                        System.out.println(node+"上线");
                        String[] strings = node.split(":");
                        balancer.add(new RpcClient(strings[0],Integer.parseInt(strings[1])));
                        children.add(node);
//                        System.out.println(balancer.size());
                    }
                });

            }
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
              while (true){
                  try {
                      Thread.sleep(10000);//表示每5秒循环一次
                      //获取节点内的时间
                      children.forEach(node->{
                          String data = (String) zkClient.readData(path + "/" + node);
                          if (data != null&&data.length()!=0){
                              //解析data
                              String[] strings = data.split(",");
                              Long lasttime = Long.valueOf(strings[0]);
                              Instant last = Instant.ofEpochMilli(lasttime);
                              Instant now = Instant.now();
                              long seconds = Duration.between(last, now).getSeconds();
                              System.out.println("与当前的时间差是"+seconds);
                              if (seconds>=10){
                                  zkClient.writeData(path+"/"+node, "");//将节点内的值更新为空
                              }
                          }
                      });

                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
            }
        }).start();

    }

    private void handlechildren(List<String>children){
        children.forEach(node->{
            String[] strings = node.split(":");
            balancer.add(new RpcClient(strings[0],Integer.parseInt(strings[1])));
        });
    }

    //轮询获取rpcclient
    //修改获取方案
    public  RpcClient next(){
        String path = "/rpcservice";
        Integer responseTime = Integer.MAX_VALUE;
        int resultindex =-1;
        for (int i = 0; i <children.size() ; i++) {
            String readData = zkClient.readData(path + "/" + children.get(i));
            if (readData==null||readData.length()==0){
                //如果没有值表示是新启动的优先使用
                return balancer.get(i);
            }
            //取出上一次的响应时间
            String responseTimeStr = readData.split(",")[1];
             resultindex = responseTime<Integer.parseInt(responseTimeStr) ? resultindex :i;
             //如果响应时间
             responseTime =  responseTime<Integer.parseInt(responseTimeStr) ? responseTime:Integer.parseInt(responseTimeStr);

            System.out.println(children.get(i)+"响应时间间隔为:"+responseTimeStr);

        }
        return balancer.get(resultindex);
    }
}
